home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / ole2book.zip / CHAP10.ZIP / CHAP10 / SCHMOO / IDROPTGT.CPP < prev    next >
C/C++ Source or Header  |  1993-06-13  |  10KB  |  374 lines

  1. /*
  2.  * IDROPTGT.CPP
  3.  *
  4.  * Implementation of the IDropTarget interface.
  5.  *
  6.  * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  7.  *
  8.  * Kraig Brockschmidt, Software Design Engineer
  9.  * Microsoft Systems Developer Relations
  10.  *
  11.  * Internet  :  kraigb@microsoft.com
  12.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  13.  */
  14.  
  15.  
  16. #include "schmoo.h"
  17.  
  18.  
  19.  
  20. /*
  21.  * CDropTarget::CDropTarget
  22.  * CDropTarget::~CDropTarget
  23.  *
  24.  * Constructor Parameters:
  25.  *  pDoc            LPCSchmooDoc of the document containing us.
  26.  */
  27.  
  28. CDropTarget::CDropTarget(LPCSchmooDoc pDoc)
  29.     {
  30.     m_cRef=0;
  31.     m_pDoc=pDoc;
  32.  
  33.     m_pIDataObject=NULL;
  34.     return;
  35.     }
  36.  
  37.  
  38. CDropTarget::~CDropTarget(void)
  39.     {
  40.     return;
  41.     }
  42.  
  43.  
  44.  
  45.  
  46. /*
  47.  * CDropTarget::QueryInterface
  48.  * CDropTarget::AddRef
  49.  * CDropTarget::Release
  50.  *
  51.  * Purpose:
  52.  *  IUnknown members for CDropTarget object.
  53.  */
  54.  
  55. STDMETHODIMP CDropTarget::QueryInterface(REFIID riid, LPVOID FAR *ppv)
  56.     {
  57.     *ppv=NULL;
  58.  
  59.     //Any interface on this object is the object pointer.
  60.     if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IDropTarget))
  61.         *ppv=(LPVOID)this;
  62.  
  63.     /*
  64.      * If we actually assign an interface to ppv we need to AddRef it
  65.      * since we're returning a new pointer.
  66.      */
  67.     if (NULL!=*ppv)
  68.         {
  69.         ((LPUNKNOWN)*ppv)->AddRef();
  70.         return NOERROR;
  71.         }
  72.  
  73.     return ResultFromScode(E_NOINTERFACE);
  74.     }
  75.  
  76.  
  77. STDMETHODIMP_(ULONG) CDropTarget::AddRef(void)
  78.     {
  79.     return ++m_cRef;
  80.     }
  81.  
  82. STDMETHODIMP_(ULONG) CDropTarget::Release(void)
  83.     {
  84.     ULONG           cRefT;
  85.  
  86.     cRefT=--m_cRef;
  87.  
  88.     if (0L==m_cRef)
  89.         delete this;
  90.  
  91.     return cRefT;
  92.     }
  93.  
  94.  
  95.  
  96.  
  97.  
  98. /*
  99.  * CDropTarget::DragEnter
  100.  *
  101.  * Purpose:
  102.  *  Indicates that data in a drag operation has been dragged over our
  103.  *  window that's a potential target.  We are to decide if it's something
  104.  *  we're interested in or not.
  105.  *
  106.  * Parameters:
  107.  *  pIDataSource    LPDATAOBJECT providing the source data.
  108.  *  grfKeyState     DWORD flags indicating states of keys and mouse buttons.
  109.  *  pt              POINTL coordinates in the client space of the document.
  110.  *  pdwEffect       LPDWORD into which we'll place the appropriate effect
  111.  *                  flag for this point.
  112.  *
  113.  * Return Value:
  114.  *  SCODE           NOERROR
  115.  */
  116.  
  117. STDMETHODIMP CDropTarget::DragEnter(LPDATAOBJECT pIDataSource
  118.     , DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
  119.     {
  120.     HWND        hWnd;
  121.  
  122.     /*
  123.      *  1.  Use IDataObject::EnumFormatEtc and IDataObject::QueryGetData
  124.      *      to determine if it has usable data. The conditions for a drop
  125.      *      are generally the same as for pasting. If pasting isn't possible,
  126.      *      store DROPEFFECT_NONE in *pdwEffect and return NOERROR.
  127.      *
  128.      *  2.  Determine if you can drop on the point in pt.  If not, store
  129.      *      DROPEFFECT_NONE in *pdwEffect and return NOERROR.
  130.      *
  131.      *  3.  Determine what effect a drop may have at pt and store the
  132.      *      effect flag in pdwEffect.
  133.      *
  134.      *  4.  If you want IDataObject in DragOver, save it and AddRef
  135.      *      it here.
  136.      *
  137.      *  5.  Provide some user feedback and return NOERROR.
  138.      */
  139.  
  140.     /*
  141.      * 1.  Check if we can paste from the pIDataSource we're provided.
  142.      *     We already made this nice useful function to test.
  143.      */
  144.  
  145.     m_pIDataObject=NULL;
  146.  
  147.     if (!m_pDoc->FQueryPasteFromData(pIDataSource))
  148.         {
  149.         *pdwEffect=DROPEFFECT_NONE;
  150.         return NOERROR;
  151.         }
  152.  
  153.  
  154.     //2.  We can always drop anywhere in our document, so pt is uninteresting.
  155.  
  156.  
  157.     /*
  158.      * 3. We return either a COPY or MOVE effect flag, depending on the
  159.      *    state of the grfKeyState flags.  We MOVE on no key or Shift key,
  160.      *    COPY on Ctrl key.
  161.      */
  162.  
  163.     //Default is move
  164.     *pdwEffect=DROPEFFECT_MOVE;
  165.  
  166.     if (grfKeyState & MK_CONTROL)
  167.         *pdwEffect=DROPEFFECT_COPY;
  168.  
  169.     /*
  170.      * 4. We really don't need to keep the IDataObject around since we're
  171.      *    not interested in it in DragOver.  However, we'll save it just
  172.      *    for demonstration.
  173.      */
  174.     m_pIDataObject=pIDataSource;
  175.     m_pIDataObject->AddRef();
  176.  
  177.     /*
  178.      * 5.  We always accept drops of our data on us, so we only need to
  179.      *     provide some UI feedback here which we do by inverting the edge
  180.      *     of the polyline window in this document.  We'll remove this in
  181.      *     DragLeave and in Drop.  DragOver won't effect it since we can
  182.      *     always drop.
  183.      *
  184.      *     Since we're inverting a border, insure that this window is on top.
  185.      */
  186.  
  187.     hWnd=m_pDoc->Window();
  188.     BringWindowToTop(hWnd);
  189.     UpdateWindow(hWnd);
  190.     m_pDoc->DropSelectTargetWindow();
  191.  
  192.     return NOERROR;
  193.     }
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200. /*
  201.  * CDropTarget::DragOver
  202.  *
  203.  * Purpose:
  204.  *  Indicates that the mouse was moved inside the window represented
  205.  *  by this drop target.  This happens on every WM_MOUSEMOVE, so this
  206.  *  function should be very efficient.
  207.  *
  208.  * Parameters:
  209.  *  grfKeyState     DWORD providing the current keyboard and mouse states
  210.  *  pt              POINTL where the mouse currently is.
  211.  *  pdwEffect       LPDWORD in which to store the effect flag for this point.
  212.  *
  213.  * Return Value:
  214.  *  SCODE           NOERROR
  215.  */
  216.  
  217. STDMETHODIMP CDropTarget::DragOver(DWORD grfKeyState, POINTL pt
  218.     , LPDWORD pdwEffect)
  219.     {
  220.     /*
  221.      *  1.  Check if dropping is currently kosher at pt given the current
  222.      *      key states and the data available in the data object.  Remember
  223.      *      if you want a data object here, save and AddRef it in DragEnter.
  224.      *
  225.      *  2.  If you determine you can drop, store the effect flag in pdwEffect
  226.      *      and provide some sort of visual indication in your window of
  227.      *      the result of a drop.  If the control key is down, the effect
  228.      *      should be copy instead of move (cut).
  229.      *
  230.      *      2a. If you are within a scroll inset region defined by
  231.      *          DragScrollInset, start a timer using DragScrollDelay count.
  232.      *          When it elapses, scroll your document.
  233.      *
  234.      *      2b. If you are scrolling and DragOver leaves the inset region,
  235.      *          stop scrolling.
  236.      *
  237.      *  3.  Return NOERROR.
  238.      */
  239.  
  240.     if (NULL==m_pIDataObject)
  241.         {
  242.         *pdwEffect=DROPEFFECT_NONE;
  243.         return NOERROR;
  244.         }
  245.  
  246.  
  247.     //Since we can always drop, we just return effect flags based on keys.
  248.     *pdwEffect=DROPEFFECT_MOVE;
  249.  
  250.     if (grfKeyState & MK_CONTROL)
  251.         *pdwEffect=DROPEFFECT_COPY;
  252.  
  253.     return NOERROR;
  254.     }
  255.  
  256.  
  257.  
  258.  
  259.  
  260.  
  261. /*
  262.  * CDropTarget::DragLeave
  263.  *
  264.  * Purpose:
  265.  *  Informs the drop target that the operation has left its window.
  266.  *
  267.  * Parameters:
  268.  *  None
  269.  *
  270.  * Return Value:
  271.  *  SCODE           NOERROR
  272.  */
  273.  
  274. STDMETHODIMP CDropTarget::DragLeave(void)
  275.     {
  276.     /*
  277.      *  1.  If you are scrolling, stop now.
  278.      *  2.  Remove any UI feedback in your window for potential drop results.
  279.      *  3.  Release any IDataObject held from DragEnter.
  280.      *  4.  Return NOERROR.
  281.      */
  282.  
  283.     if (NULL==m_pIDataObject)
  284.         return NOERROR;
  285.  
  286.     //1.  We don't scroll, so we don't worry about timers.
  287.  
  288.     //2.  Remove the UI feedback
  289.     m_pDoc->DropSelectTargetWindow();
  290.  
  291.     //3.  Release the held IDataObject
  292.     m_pIDataObject->Release();
  293.  
  294.     return NOERROR;
  295.     }
  296.  
  297.  
  298.  
  299.  
  300.  
  301. /*
  302.  * CDropTarget::Drop
  303.  *
  304.  * Purpose:
  305.  *  Instructs the drop target to paste the data that was just now dropped
  306.  *  on it.
  307.  *
  308.  * Parameters:
  309.  *  pIDataSource    LPDATAOBJECT from which we'll paste.
  310.  *  grfKeyState     DWORD providing current keyboard/mouse state.
  311.  *  pt              POINTL at which the drop occurred.
  312.  *  pdwEffect       LPDWORD in which to store what you do with the data.
  313.  *
  314.  * Return Value:
  315.  *  SCODE           NOERROR
  316.  */
  317.  
  318. STDMETHODIMP CDropTarget::Drop(LPDATAOBJECT pIDataSource
  319.     , DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
  320.     {
  321.     BOOL        fRet=TRUE;
  322.  
  323.     /*
  324.      *  1.  If you have a scrolling timer active, stop it now.
  325.      *
  326.      *  2.  Remove any UI feedback in your window for potential drop
  327.      *      results.
  328.      *
  329.      *  3.  Release any IDataObject held from DragEnter:  use pIDataSource.
  330.      *
  331.      *  4.  If you cannot drop here, release the IDataObject from
  332.      *      DragEnter and return E_FAIL.
  333.      *
  334.      *  5.  Effectively do a paste operation using the data in the
  335.      *      IDataObject held from DragEnter at the point pt modified
  336.      *      by the key and mouse button states in grfKeyState.
  337.      *
  338.      *  6.  Store what you did with the data in pdwEffect and return NOERROR.
  339.      */
  340.  
  341.     *pdwEffect=DROPEFFECT_NONE;
  342.  
  343.  
  344.     if (NULL==m_pIDataObject)
  345.         return ResultFromScode(E_FAIL);
  346.  
  347.     //1.  We don't scroll, so we don't worry about timers.
  348.  
  349.     //2.  Remove the UI feedback
  350.     m_pDoc->DropSelectTargetWindow();
  351.  
  352.     //3.  Release the held IDataObject from DragEnter
  353.     m_pIDataObject->Release();
  354.  
  355.  
  356.     //No point in drag-drop to ourselves (for Schmoo, at least)
  357.     if (m_pDoc->m_fDragSource)
  358.         return ResultFromScode(E_FAIL);
  359.  
  360.     //4, 5.  We can always drop, so we do the paste.
  361.     fRet=m_pDoc->FPasteFromData(pIDataSource);
  362.  
  363.     //6.  Store what we're doing in pdwEffect.
  364.     if (!fRet)
  365.         return ResultFromScode(E_FAIL);
  366.  
  367.     *pdwEffect=DROPEFFECT_MOVE;
  368.  
  369.     if (grfKeyState & MK_CONTROL)
  370.         *pdwEffect=DROPEFFECT_COPY;
  371.  
  372.     return NOERROR;
  373.     }
  374.